home *** CD-ROM | disk | FTP | other *** search
- # -*- coding: utf-8 -*-
- """
- """
-
- __author__ = 'Robert Ancell <bob27@users.sourceforge.net>'
- __license__ = 'GNU General Public License Version 2'
- __copyright__ = 'Copyright 2005-2006 Robert Ancell'
-
- import board
-
- CHECK = '+'
- CHECKMATE = '#'
-
- # Notation for takes
- MOVE = '-'
- TAKE = 'x'
-
- # Castling moves
- CASTLE_SHORT = 'o-o'
- CASTLE_LONG = 'o-o-o'
-
- # Characters used to describe pieces
- _typeToLAN = {board.PAWN: 'P',
- board.KNIGHT: 'N',
- board.BISHOP: 'B',
- board.ROOK: 'R',
- board.QUEEN: 'Q',
- board.KING: 'K'}
- _lanToType = {}
- for (pieceType, character) in _typeToLAN.iteritems():
- _lanToType[character] = pieceType
- _lanToType[character.lower()] = pieceType # English pieces are sometimes written in lowercase
-
- class DecodeError(Exception):
- """
- """
- pass
-
- def _checkLocation(location):
- """
- """
- if len(location) != 2:
- raise DecodeError('Invalid length location')
- if location[0] < 'a' or location[0] > 'h':
- raise DecodeError('Invalid rank')
- if location[1] < '0' or location[1] > '8':
- raise DecodeError('Invalid file')
- return location
-
- def decode(colour, move):
- """Decode a long algebraic format move.
-
- 'colour' is the colour of the player making the move (board.WHITE or board.BLACK).
- 'move' is the move description (string).
-
- Returns a tuple containing (start, end, piece, moveType, promotionType, result)
- 'start' is the location being moved from (string, e.g. 'a1', 'h8').
- 'end' is the location being moved to (string, e.g. 'a1', 'h8').
- 'piece' is the piece being moved (board.PAWN, board.ROOK, ... or None if not specified).
- 'moveType' is a flag to show if this move takes an oppoenent piece (MOVE, TAKE or None if not specified).
- 'promotionType' is the piece type to promote to (board.ROOK, board.KNIGHT, ... or None if not specified).
- 'check' is the result after the move (CHECK, CHECKMATE or None if not specified).
-
- Raises DecodeError if the move is unable to be decoded.
- """
- pieceType = None
- promotionType = None
- moveType = None
- result = None
-
- m = move
-
- if colour is board.WHITE:
- baseFile = '1'
- else:
- baseFile = '8'
- if m == CASTLE_SHORT:
- return ('e' + baseFile, 'g' + baseFile, None, None, None, None)
- elif m == CASTLE_LONG:
- return ('e' + baseFile, 'c' + baseFile, None, None, None, None)
-
- # First character can be the piece types
- if len(m) < 1:
- raise DecodeError('Too short')
- try:
- pieceType = _lanToType[m[0]]
- except KeyError:
- pieceType = None
- else:
- m = m[1:]
-
- if len(m) < 2:
- raise DecodeError('Too short')
- try:
- start = _checkLocation(m[:2])
- except DecodeError, e:
- if pieceType is None:
- raise e
- # Perhaps the first character wasn't a piece type
- m = move
- start = _checkLocation(m[:2])
- pieceType = None
- m = m[2:]
-
- if len(m) < 1:
- raise DecodeError('Too short')
- if m[0] == MOVE or m[0] == TAKE:
- moveType = m[0]
- m = m[1:]
-
- if len(m) < 2:
- raise DecodeError('Too short')
- end = _checkLocation(m[:2])
- m = m[2:]
-
- # Look for promotion type, note this can be in upper or lower case
- if len(m) > 0:
- if m[0] == '=':
- if len(m) < 2:
- raise DecodeError('Too short')
- try:
- promotionType = _lanToType[m[1]]
- except KeyError:
- raise DecodeError('Unknown promotion type')
- m = m[2:]
- else:
- try:
- promotionType = _lanToType[m[0]]
- except KeyError:
- pass
- else:
- m = m[1:]
-
- if len(m) == 1:
- if m == CHECK or m == CHECKMATE:
- result = m
- m = ''
- elif len(m) == 2:
- if m == '++':
- result = CHECKMATE
- m = ''
-
- if len(m) != 0:
- raise DecodeError('Extra characters')
-
- return (start, end, pieceType, moveType, promotionType, result)
-
- def encode(colour, start, end, piece = None, moveType = None, promotionType = None, result = None):
- """Encode a long algebraic format move.
-
- 'start' is the location being moved from (string, e.g. 'a1', 'h8').
- 'end' is the location being moved to (string, e.g. 'a1', 'h8').
- 'piece' is the piece being moved (board.PAWN, board.ROOK, ... or None if not specified).
- 'moveType' is a flag to show if this move takes an oppoenent piece (MOVE, TAKE or None if not specified).
- 'promotionType' is the piece type to promote to (board.ROOK, board.KNIGHT, ... or None if not specified).
- 'check' is the result after the move (CHECK, CHECKMATE or None if not specified).
-
- Returns a string describing this move.
- """
- try:
- _checkLocation(start)
- _checkLocation(end)
- except DecodeError:
- raise TypeError("Invalid values for 'start' and 'end'")
-
- string = ''
-
- # Report the piece being moved
- if piece is not None:
- string += _typeToLAN[piece]
-
- # Report the source location
- string += start
-
- # Report if this is a move or a take
- if moveType != None:
- string += moveType
-
- # Report the target location
- string += end
-
- # Report the promotion type
- # FIXME: Only report if a pawn promotion
- if promotionType != None:
- if False: # FIXME: What to name this flag?
- string += '='
- string += _typeToLAN[promotionType].lower()
-
- # Report the check result
- if result is not None:
- string += result
-
- return string
-